﻿namespace DependencyPropertyChangedSample.Extensions
{
    using System;
    using System.Windows;
    using System.Windows.Media.Animation;
    using DependencyPropertyChangedSample.ComponentModel;

    public static class StoryboardExtensions
    {
        /// <summary>
        /// Create a animation with a default easing function
        /// </summary>
        public static Timeline CreateDoubleAnimation(this Storyboard storyboard, Duration duration, double from, double to)
        {
            return storyboard.CreateDoubleAnimation(duration, from, to,
                new SineEase
                {
                    EasingMode = EasingMode.EaseInOut
                });
        }

        /// <summary>
        /// Create a animation with a custom easing function
        /// </summary>
        public static Timeline CreateDoubleAnimation(this Storyboard storyboard, Duration duration, double from, double to, IEasingFunction easingFunction)
        {
            var animation = new DoubleAnimation
            {
                From = from,
                To = to,
                Duration = duration,
                EasingFunction = easingFunction
            };
            return animation;
        }

        private static Timeline CreatePointAnimation(this Storyboard storyboard, FrameworkElement fe, Duration duration, Point from, Point to, IEasingFunction easingFunction)
        {
            var pointAnimation = new PointAnimation()
            {
                Duration = duration,
                From = from,
                To = to,
                EasingFunction = easingFunction
            };

            var distributionHelper = new DependencyPropertyDistributionHelper<Point>(fe, (o, e) => (o as UIElement).SetCanvasPoint(e));
            storyboard.Children.Add(pointAnimation);

            Storyboard.SetTarget(pointAnimation, distributionHelper);
            Storyboard.SetTargetProperty(pointAnimation, new PropertyPath(DependencyPropertyDistributionHelper<Point>.TargetProperty));

            return pointAnimation;
        }

        /// <summary>
        /// Add an animation to an existing storyboard
        /// </summary>
        public static void AddAnimation(this Storyboard storyboard, DependencyObject item, Timeline t, DependencyProperty p)
        {
            if (p == null) throw new ArgumentNullException("p");
            Storyboard.SetTarget(t, item);
            Storyboard.SetTargetProperty(t, new PropertyPath(p));
            storyboard.Children.Add(t);
        }

        /// <summary>
        /// Add a translation animation to an existing storyboard with a 
        /// default easing function
        /// </summary>
        public static void AddTranslationAnimation(this Storyboard storyboard, FrameworkElement fe, Point from, Point to, Duration duration)
        {
            storyboard.AddTranslationAnimation(fe, from, to, duration, null);
        }

        /// <summary>
        /// Add a translation animation to an existing storyboard with a 
        /// custom easing function
        /// </summary>
        public static void AddTranslationAnimation(this Storyboard storyboard, FrameworkElement fe, Point from, Point to, Duration duration, IEasingFunction easingFunction)
        {
            storyboard.CreatePointAnimation(fe, duration, from, to, easingFunction);
        }
    }
}
